import type {
  ActionType,
  PageInfo,
  ParamsType,
  ProColumns,
  RequestData,
} from '@ant-design/pro-components';
import { EditableProTable, FooterToolbar, ProCard } from '@ant-design/pro-components';
import {
    Button,
    Checkbox,
    CheckboxProps,
    Input,
    message,
    Tree,
    TreeDataNode,
    TreeProps,
  } from 'antd';
import { FormattedMessage, useIntl } from '@umijs/max';
import { debounce } from 'lodash';
import React, { useCallback, useEffect, useRef, useState } from 'react';

const { Search } = Input;

interface EditTreeTableProps<T, U> {
  removeRule?: (keys: T[]) => Promise<void>;
  columns: ProColumns<T>[];
  onRowClick?: (entity: T) => void;
  renderToolBar?: () => React.ReactNode[];
  request: (params: U, sorter: any, filter: any) => Promise<RequestData<T>>;
  onOK?: (params: T) => Promise<void>;
  treeDataSource: TreeDataNode[];
  treeTitle?: string;
  checkTitle?: string;
  searchPlaceholder?: string;
  renderExtraContent?: () => React.ReactNode;
}

const EditTreeTable = <T extends Record<string, any>, U extends ParamsType>({
  removeRule,
  columns,
  renderToolBar,
  request,
  onOK,
  treeDataSource,
  treeTitle = '部门信息',
  checkTitle = '包含下级',
  searchPlaceholder = '请输入',
  renderExtraContent,
}: EditTreeTableProps<T, U>) => {
  const actionRef = useRef<ActionType>();
  const [selectedRowsState, setSelectedRows] = useState<T[]>([]);
  const intl = useIntl();
  const [messageApi, contextHolder] = message.useMessage();
  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  const [pageInfo, setPageInfo] = useState<PageInfo>({ current: 1, pageSize: 20, total: 1 });
  const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]); // 选中的树节点
  const [checkStrictly, setcheckStrictly] = useState<boolean>(false); // 控制树节点是否严格检查
  const [treeData, setTreeData] = useState<TreeDataNode[]>(treeDataSource); // 树节点数据

  useEffect(() => {
    setTreeData(treeDataSource);
  });
  // 处理树节点选中事件
  const onCheck: TreeProps['onCheck'] = (checkedKeysValue) => {
    setCheckedKeys(checkedKeysValue as React.Key[]);
    actionRef.current?.reload();
  };

  const handleRemove = useCallback(async () => {
    if (!selectedRowsState?.length) {
      messageApi.warning('请选择删除项');
      return;
    }
    await removeRule?.(selectedRowsState);
    setSelectedRows([]);
    actionRef.current?.reloadAndRest?.();
    messageApi.success('删除成功，即将刷新！');
  }, [removeRule, selectedRowsState]);

  const onFinish = async (value: T) => {
    onOK?.(value);
  };

  // 处理复选框变化
  const checkChange: CheckboxProps['onChange'] = (e) => {
    setcheckStrictly(e.target.checked);
  };

  // 搜索树节点并进行过滤
  const searchTree = useCallback(
    debounce((value: string) => {
      if (!value) {
        setTreeData(treeDataSource);
        return;
      }
      const filterTree = (nodes: TreeDataNode[], searchText: string): TreeDataNode[] => {
        return nodes
          .map((node) => {
            const titleIncludesSearchText = node.title
              ?.toString()
              .toLowerCase()
              .includes(searchText.toLowerCase());

            if (!node.children) {
              return titleIncludesSearchText ? { ...node } : null;
            }
            const filteredChildren = filterTree(node.children, searchText);
            if (filteredChildren.length > 0 || titleIncludesSearchText) {
              return { ...node, children: filteredChildren };
            }
            return null;
          })
          .filter(Boolean) as TreeDataNode[];
      };
      setTreeData(filterTree(treeDataSource, value));
    }, 300),
    [treeDataSource],
  );

  // 处理搜索输入变化
  const searchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    searchTree(e.target.value);
  };

  // 树节点和搜索输入框的额外内容
  const defaultExtraContent = (
    <div style={{ lineHeight: 3 }}>
      <Search
        placeholder={searchPlaceholder}
        onSearch={(value) => searchTree(value)}
        onChange={searchChange}
      />
      <Checkbox onChange={checkChange}>{checkTitle}</Checkbox>
      <Tree
        checkable
        onCheck={onCheck}
        checkedKeys={checkedKeys}
        treeData={treeData}
        checkStrictly={!checkStrictly}
        defaultExpandAll={true}
      />
    </div>
  );

  const extraContent = renderExtraContent ? renderExtraContent() : defaultExtraContent;

  return (
    <>
      {contextHolder}
      <ProCard style={{ marginBlockStart: 8 }} gutter={8} ghost>
        <ProCard title={treeTitle} colSpan="25%" style={{ height: '100%' }}>
          {extraContent}
        </ProCard>
        <ProCard>
          <EditableProTable<T>
            rowKey="code"
            headerTitle={intl.formatMessage({
              id: 'pages.searchTable.title',
              defaultMessage: 'Enquiry form',
            })}
            pagination={{
              pageSize: pageInfo.pageSize,
              current: pageInfo.current,
              total: pageInfo.total,
              showTotal: (total, range) => `第 ${range[0]}-${range[1]} 条/总共 ${total} 条`,
              onChange: (page, pageSize) => {
                setPageInfo({ current: page, pageSize, total: pageInfo.total });
              },
            }}
            actionRef={actionRef}
            maxLength={0}
            scroll={{ x: 960 }}
            toolBarRender={renderToolBar}
            search={{ labelWidth: 120 }}
            loading={false}
            columns={columns}
            request={async (params, sorter, filter) => {
              const response = await request(params as U, sorter, filter);
              return {
                data: response.data,
                total: response.total,
                success: response.success,
              };
            }}
            editable={{
              type: 'multiple',
              editableKeys,
              onSave: async (rowKey, data) => await onFinish(data),
              onChange: setEditableRowKeys,
              actionRender: (row, config, defaultDom) => [defaultDom.save, defaultDom.cancel],
            }}
            rowSelection={{
              onChange: (_, selectedRows) => setSelectedRows(selectedRows),
            }}
          />
          {selectedRowsState?.length > 0 && (
            <FooterToolbar
              extra={
                <div>
                  <FormattedMessage id="pages.searchTable.chosen" defaultMessage="Chosen" />{' '}
                  <a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
                  <FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
                </div>
              }
            >
              <Button onClick={handleRemove}>
                <FormattedMessage
                  id="pages.searchTable.batchDeletion"
                  defaultMessage="Batch deletion"
                />
              </Button>
            </FooterToolbar>
          )}
        </ProCard>
      </ProCard>
    </>
  );
};

export default EditTreeTable;
